package com.ltv.xiangqiplugin.utils;

import com.ltv.xiangqiplugin.models.Game;
import com.ltv.xiangqiplugin.models.SquareCoord;

public class MoveUtils {
	
	private static final char TIEN = '.';
	private static final char THOAI = '/';
	private static final char BINH = '-';
	
	private static final char RED = 'r';
	private static final char BLUE = 'b';
	
	public static String getVnMove(String move, Game game) {
		if (move == null) {
			return "";
		}
		
		int dashIndex = move.indexOf('-');
		if (dashIndex != 2 && dashIndex != 3) {
			return "";
		}
		
		SquareCoord origin = new SquareCoord(move.substring(0, move.indexOf('-')));
		SquareCoord destin = new SquareCoord(move.substring(move.indexOf('-')+1));
		
		char piece = game.pieceAtCoord(origin);
		
		try {
			char gameAction = getGameAction(move, game);
			String additionSymbol = "";
			
			switch (gameAction) {
			case BINH:
				switch (piece) {
				case 'R': case 'r':
					additionSymbol = getAdditionalSymbol(piece, game, origin);
					if (additionSymbol.equals("")) {
						return "X" + toVnCol(piece, origin.toString().charAt(0))
								+ BINH + toVnCol(piece, destin.toString().charAt(0));
					} else {
						return "X" + additionSymbol
								+ BINH + toVnCol(piece, destin.toString().charAt(0));
					}
				case 'C': case 'c':
					additionSymbol = getAdditionalSymbol(piece, game, origin);
					if (additionSymbol.equals("")) {
						return "P" + toVnCol(piece, origin.toString().charAt(0))
								+ BINH + toVnCol(piece, destin.toString().charAt(0));
					} else {
						return "P" + additionSymbol
								+ BINH + toVnCol(piece, destin.toString().charAt(0));
					}
				case 'P': case 'p':
					additionSymbol = getAdditionalSymbol(piece, game, origin);
					if (additionSymbol.equals("")) {
						return "B" + toVnCol(piece, origin.toString().charAt(0))
								+ BINH + toVnCol(piece, destin.toString().charAt(0));
					} else {
						return "B" + additionSymbol
								+ BINH + toVnCol(piece, destin.toString().charAt(0));
					}
				case 'K': case 'k':
					return "Tg" + BINH + toVnCol(piece, destin.toString().charAt(0));
				default:
					break;
				}
			case TIEN:
				switch (piece) {
				case 'R': case 'r':
					additionSymbol = getAdditionalSymbol(piece, game, origin);
					if (additionSymbol.equals("")) {
						return "X" + toVnCol(piece, origin.toString().charAt(0))
								+ TIEN + Math.abs((destin.getRow() - origin.getRow()));
					} else {
						return "X" + additionSymbol
								+ TIEN + Math.abs((destin.getRow() - origin.getRow()));
					}
				case 'C': case 'c':
					additionSymbol = getAdditionalSymbol(piece, game, origin);
					if (additionSymbol.equals("")) {
						return "P" + toVnCol(piece, origin.toString().charAt(0))
								+ TIEN + Math.abs((destin.getRow() - origin.getRow()));
					} else {
						return "P" + additionSymbol
								+ TIEN + Math.abs((destin.getRow() - origin.getRow()));
					}
				case 'P':case 'p':
					additionSymbol = getAdditionalSymbol(piece, game, origin);
					if (additionSymbol.equals("")) {
						return "B" + toVnCol(piece, origin.toString().charAt(0))
								+ TIEN + "1";
					} else {
						return "B" + additionSymbol
								+ TIEN + "1";
					}
				case 'K':case 'k':
					return "Tg" + TIEN + "1";
				case 'H':case 'h':
					additionSymbol = getAdditionalSymbol(piece, game, origin);
					if (additionSymbol.equals("")) {
						return "M" + toVnCol(piece, origin.toString().charAt(0))
								+ TIEN + toVnCol(piece, destin.toString().charAt(0));
					} else {
						return "M" + additionSymbol
								+ TIEN + toVnCol(piece, destin.toString().charAt(0));
					}
				case 'E':case 'e':
					return "T" + toVnCol(piece, origin.toString().charAt(0))
							+ TIEN + toVnCol(piece, destin.toString().charAt(0));
				case 'A':case 'a':
					return "S" + toVnCol(piece, origin.toString().charAt(0))
							+ TIEN + toVnCol(piece, destin.toString().charAt(0));
				default:
					break;
				}
			case THOAI:
				switch (piece) {
				case 'R': case 'r':
					additionSymbol = getAdditionalSymbol(piece, game, origin);
					if (additionSymbol.equals("")) {
						return "X" + toVnCol(piece, origin.toString().charAt(0))
								+ THOAI + Math.abs((destin.getRow() - origin.getRow()));
					} else {
						return "X" + additionSymbol
								+ THOAI + Math.abs((destin.getRow() - origin.getRow()));
					}
				case 'C': case 'c':
					additionSymbol = getAdditionalSymbol(piece, game, origin);
					if (additionSymbol.equals("")) {
						return "P" + toVnCol(piece, origin.toString().charAt(0))
								+ THOAI + Math.abs((destin.getRow() - origin.getRow()));
					} else {
						return "P" + additionSymbol
								+ THOAI + Math.abs((destin.getRow() - origin.getRow()));
					}
				case 'K':case 'k':
					return "Tg" + THOAI + "1";
				case 'H':case 'h':
					additionSymbol = getAdditionalSymbol(piece, game, origin);
					if (additionSymbol.equals("")) {
						return "M" + toVnCol(piece, origin.toString().charAt(0))
								+ THOAI + toVnCol(piece, destin.toString().charAt(0));
					} else {
						return "M" + additionSymbol
								+ THOAI + toVnCol(piece, destin.toString().charAt(0));
					}
				case 'E':case 'e':
					return "T" + toVnCol(piece, origin.toString().charAt(0))
							+ THOAI + toVnCol(piece, destin.toString().charAt(0));
				case 'A':case 'a':
					return "S" + toVnCol(piece, origin.toString().charAt(0))
							+ THOAI + toVnCol(piece, destin.toString().charAt(0));
				default:
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return "[" + move + "]";
	}
	
	private static int toVnCol(char piece, char pgnCol) throws Exception {
		if (piece == 'R' || piece == 'H' || piece == 'E' || piece == 'A' || piece == 'K' || piece == 'C' || piece == 'P') {
			return 'i' - pgnCol + 1;
		} else if (piece == 'r' || piece == 'h' || piece == 'e' || piece == 'a' || piece == 'k' || piece == 'c' || piece == 'p') {
			return pgnCol - 'a' + 1;
		} else {
			throw new Exception("Invalid piece symbol: " + piece);
		}
	}
	
	private static char getGameAction(String move, Game game) throws Exception {
		
		SquareCoord origin = new SquareCoord(move.substring(0, move.indexOf('-')));
		SquareCoord destin = new SquareCoord(move.substring(move.indexOf('-')+1));
		
		if (origin.getRow() == destin.getRow()) {
			return BINH;
		}
		
		char piece = game.pieceAtCoord(origin);
		char pieceType = getPieceType(piece);
		
		if (pieceType == RED) {
			if (origin.getRow() < destin.getRow()) {
				return TIEN;
			} else {
				return THOAI;
			}
		} else if (pieceType == BLUE) {
			if (origin.getRow() > destin.getRow()) {
				return TIEN;
			} else {
				return THOAI;
			}
		} else {
			throw new Exception("Invalid piece symbol: " + piece);
		}
	}
	
	private static char getPieceType(char piece) throws Exception {
		if (piece == 'R' || piece == 'H' || piece == 'E' || piece == 'A' || piece == 'K' || piece == 'C' || piece == 'P') {
			return RED;
		} else if (piece == 'r' || piece == 'h' || piece == 'e' || piece == 'a' || piece == 'k' || piece == 'c' || piece == 'p') {
			return BLUE;
		} else {
			throw new Exception("Invalid piece symbol: " + piece);
		}
	}
	
	private static String getAdditionalSymbol(char piece, Game game, SquareCoord coord) {
		String ret = "";
		switch (piece) {
		case 'R':
			for (int i = 1; i <= 10; i++) {
				if (i != coord.getRow() + 1) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'R') {
						if (i > coord.getRow() + 1) {
							return "s";
						} else {
							return "t";
						}
					}
				}
			}
			break;
		case 'r':
			for (int i = 1; i <= 10; i++) {
				if (i != coord.getRow() + 1) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'r') {
						if (i > coord.getRow() + 1) {
							return "t";
						} else {
							return "s";
						}
					}
				}
			}
			break;
		case 'C':
			for (int i = 1; i <= 10; i++) {
				if (i != coord.getRow() + 1) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'C') {
						if (i > coord.getRow() + 1) {
							return "s";
						} else {
							return "t";
						}
					}
				}
			}
			break;
		case 'c':
			for (int i = 1; i <= 10; i++) {
				if (i != coord.getRow() + 1) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'c') {
						if (i > coord.getRow() + 1) {
							return "t";
						} else {
							return "s";
						}
					}
				}
			}
			break;
		case 'H':
			for (int i = 1; i <= 10; i++) {
				if (i != coord.getRow() + 1) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'H') {
						if (i > coord.getRow() + 1) {
							return "s";
						} else {
							return "t";
						}
					}
				}
			}
			break;
		case 'h':
			for (int i = 1; i <= 10; i++) {
				if (i != coord.getRow() + 1) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'h') {
						if (i > coord.getRow() + 1) {
							return "t";
						} else {
							return "s";
						}
					}
				}
			}
			break;
		case 'P':
			int numSoldier = countPieces('P', coord.toString().charAt(0), game);
			if (numSoldier == 2) {
				int a[] = new int[2];
				int aIndex = 0;
				for (int i = 1; i <= 10; i++) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'P') {
						a[aIndex] = i;
						aIndex++;
					}
				}
				int soldierIndex = 0;
				for (int i = 0; i < a.length; i++) {
					if (a[i] == coord.getRow() + 1) {
						soldierIndex = i;
						break;
					}
				}
				
				boolean check = false;
				for (char col = 'a'; col <= 'i'; col++) {
					if (col != coord.toString().charAt(0) && countPieces('P', col, game) >= 2) {
						check = true;
						break;
					}
				}
				
				if (!check) {
					switch (soldierIndex) {
					case 0:
						return "s";
					case 1:
						return "t";
					default:
						break;
					}
				} else {
					switch (soldierIndex) {
					case 0:
						return ('i' - coord.toString().charAt(0) + 1) + "s";
					case 1:
						return ('i' - coord.toString().charAt(0) + 1) + "t";
					default:
						break;
					}
				}
			} else if (numSoldier == 3) {
				int a[] = new int[3];
				int aIndex = 0;
				for (int i = 1; i <= 10; i++) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'P') {
						a[aIndex] = i;
						aIndex++;
					}
				}
				int soldierIndex = 0;
				for (int i = 0; i < a.length; i++) {
					if (a[i] == coord.getRow() + 1) {
						soldierIndex = i;
						break;
					}
				}
				boolean check = false;
				for (char col = 'a'; col <= 'i'; col++) {
					if (col != coord.toString().charAt(0) && countPieces('P', col, game) >= 2) {
						check = true;
						break;
					}
				}
				
				if (!check) {
					switch (soldierIndex) {
					case 0:
						return "s";
					case 1:
						return "g";
					case 2:
						return "t";
					default:
						break;
					}
				} else {
					switch (soldierIndex) {
					case 0:
						return ('i' - coord.toString().charAt(0) + 1) + "s";
					case 1:
						return "g";
					case 2:
						return ('i' - coord.toString().charAt(0) + 1) + "t";
					default:
						break;
					}
				}
			} else if (numSoldier == 4) {
				int a[] = new int[4];
				int aIndex = 0;
				for (int i = 1; i <= 10; i++) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'P') {
						a[aIndex] = i;
						aIndex++;
					}
				}
				int soldierIndex = 0;
				for (int i = 0; i < a.length; i++) {
					if (a[i] == coord.getRow() + 1) {
						soldierIndex = i;
						break;
					}
				}
				switch (soldierIndex) {
				case 0:
					return "s";
				case 1:
					return "gs";
				case 2:
					return "gt";
				case 3:
					return "t";
				default:
					break;
				}
			} else if (numSoldier == 5) {
				int a[] = new int[5];
				int aIndex = 0;
				for (int i = 1; i <= 10; i++) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'P') {
						a[aIndex] = i;
						aIndex++;
					}
				}
				int soldierIndex = 0;
				for (int i = 0; i < a.length; i++) {
					if (a[i] == coord.getRow() + 1) {
						soldierIndex = i;
						break;
					}
				}
				switch (soldierIndex) {
				case 0:
					return "s";
				case 1:
					return "gs";
				case 2:
					return "g";
				case 3:
					return "gt";
				case 4:
					return "t";
				default:
					break;
				}
			}
			break;
		case 'p':
			numSoldier = countPieces('p', coord.toString().charAt(0), game);
			if (numSoldier == 2) {
				int a[] = new int[2];
				int aIndex = 0;
				for (int i = 1; i <= 10; i++) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'p') {
						a[aIndex] = i;
						aIndex++;
					}
				}
				int soldierIndex = 0;
				for (int i = 0; i < a.length; i++) {
					if (a[i] == coord.getRow() + 1) {
						soldierIndex = i;
						break;
					}
				}
				
				boolean check = false;
				for (char col = 'a'; col <= 'i'; col++) {
					if (col != coord.toString().charAt(0) && countPieces('p', col, game) >= 2) {
						check = true;
						break;
					}
				}
				
				if (!check) {
					switch (soldierIndex) {
					case 0:
						return "t";
					case 1:
						return "s";
					default:
						break;
					}
				} else {
					switch (soldierIndex) {
					case 0:
						return (coord.toString().charAt(0) - 'a' + 1) + "t";
					case 1:
						return (coord.toString().charAt(0) - 'a'+ 1) + "s";
					default:
						break;
					}
				}
			} else if (numSoldier == 3) {
				int a[] = new int[3];
				int aIndex = 0;
				for (int i = 1; i <= 10; i++) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'p') {
						a[aIndex] = i;
						aIndex++;
					}
				}
				int soldierIndex = 0;
				for (int i = 0; i < a.length; i++) {
					if (a[i] == coord.getRow() + 1) {
						soldierIndex = i;
						break;
					}
				}
				boolean check = false;
				for (char col = 'a'; col <= 'i'; col++) {
					if (col != coord.toString().charAt(0) && countPieces('p', col, game) >= 2) {
						check = true;
						break;
					}
				}
				
				if (!check) {
					switch (soldierIndex) {
					case 0:
						return "t";
					case 1:
						return "g";
					case 2:
						return "s";
					default:
						break;
					}
				} else {
					switch (soldierIndex) {
					case 0:
						return (coord.toString().charAt(0) - 'a' + 1) + "t";
					case 1:
						return "g";
					case 2:
						return (coord.toString().charAt(0) - 'a' + 1) + "s";
					default:
						break;
					}
				}
			} else if (numSoldier == 4) {
				int a[] = new int[4];
				int aIndex = 0;
				for (int i = 1; i <= 10; i++) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'p') {
						a[aIndex] = i;
						aIndex++;
					}
				}
				int soldierIndex = 0;
				for (int i = 0; i < a.length; i++) {
					if (a[i] == coord.getRow() + 1) {
						soldierIndex = i;
						break;
					}
				}
				switch (soldierIndex) {
				case 0:
					return "t";
				case 1:
					return "gt";
				case 2:
					return "gs";
				case 3:
					return "s";
				default:
					break;
				}
			} else if (numSoldier == 5) {
				int a[] = new int[5];
				int aIndex = 0;
				for (int i = 1; i <= 10; i++) {
					SquareCoord tmp = new SquareCoord(coord.toString().substring(0, 1) + i);
					if (game.pieceAtCoord(tmp) == 'p') {
						a[aIndex] = i;
						aIndex++;
					}
				}
				int soldierIndex = 0;
				for (int i = 0; i < a.length; i++) {
					if (a[i] == coord.getRow() + 1) {
						soldierIndex = i;
						break;
					}
				}
				switch (soldierIndex) {
				case 0:
					return "t";
				case 1:
					return "gt";
				case 2:
					return "g";
				case 3:
					return "gs";
				case 4:
					return "s";
				default:
					break;
				}
			}
			break;
		default:
			break;
		}
		return ret;
	}
	
	private static int countPieces(char piece, char col, Game game) {
		int count = 0;
		SquareCoord coord;
		for (int i = 1; i <= 10; i++) {
			coord = new SquareCoord("" + col + i);
			if (game.pieceAtCoord(coord) == piece) {
				count++;
			}
		}
		return count;
	}
}
